package cn.admin.remoting.impl;

import cn.admin.remoting.SessionsFlushQueueListener;
import cn.admin.remoting.spi.SessionsFlushQueueService;
import cn.admin.remoting.util.LoggerInit;
import org.apache.mina.common.IoSession;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class SessionsFlushQueueServiceImpl implements SessionsFlushQueueService {

    private final List<SessionsFlushQueueListener> listeners = new ArrayList<>();

    SessionsFlushQueueServiceImpl() {
        DefaultClientManager.timer.scheduleWithFixedDelay(() -> {
            try {
                SessionsFlushQueueServiceImpl.this.calculatePileUpAndNotifyListeners();
            } catch (Throwable t) {
                LoggerInit.LOGGER.error(t.toString(),t);
            }
        },0L,5L, TimeUnit.SECONDS);
    }

    @Override
    public void addFlushQueueListener(SessionsFlushQueueListener listener) {
        synchronized (this.listeners) {
            if (!this.listeners.contains(listener)) {
                this.listeners.add(listener);
            }
        }
    }

    @Override
    public void removeFlushQueueListener(SessionsFlushQueueListener listener) {
        synchronized (this.listeners) {
            this.listeners.remove(listener);
        }
    }

    private void calculatePileUpAndNotifyListeners() {
        long totalPileUp = 0L;
        DefaultConnection mostPileUpConn = null;
        for (DefaultConnection conn : LCL_AliveSessionsListener.aliveSessions()) {
            IoSession session = conn.getIoSession();
            totalPileUp += (long)session.getScheduledWriteBytes();
            if (null == mostPileUpConn) {
                mostPileUpConn = conn;
            } else if (session.getScheduledWriteBytes() > mostPileUpConn.getIoSession().getScheduledWriteBytes()) {
                mostPileUpConn = conn;
            }
        }

        for (SessionsFlushQueueListener listener : this.listeners) {
            try {
                long maxPileUp = null == mostPileUpConn ? 0L :
                        (long)mostPileUpConn.getIoSession().getScheduledWriteBytes();
                listener.allSessionScheduledWriteByteIs(totalPileUp,maxPileUp,mostPileUpConn);
            } catch (Exception e) {
                LoggerInit.LOGGER.warn(e.toString(),e);
            }
        }
    }

}
